Praktikum Pengantar Sains Data

Regresi Nonlinier Lanjutan: Regression Splines dan Smoothing Splines

Author

Muhammad Yusran

Published

October 24, 2025

Pendahuluan

Pada praktikum sebelumnya, kita telah mempelajari bagaimana regresi nonlinier dapat digunakan untuk memodelkan hubungan yang tidak dapat ditangkap secara akurat oleh model regresi linier. Pendekatan regresi polinomial dan fungsi tangga memberikan fleksibilitas yang lebih tinggi dalam membentuk kurva prediksi, namun keduanya memiliki keterbatasan: regresi polinomial cenderung overfitting ketika derajatnya terlalu tinggi, sedangkan regresi fungsi tangga menghasilkan prediksi yang tersegmentasi secara diskret dan tidak kontinu.

Sebagai kelanjutannya, regression splines dan smoothing splines menawarkan pendekatan yang lebih halus dan adaptif terhadap bentuk hubungan nonlinier. Kedua metode ini merupakan bagian dari keluarga basis function regression, yang secara umum membentuk prediktor melalui transformasi tertentu dari variabel input.

Regression splines membagi domain prediktor menjadi beberapa segmen (dengan titik potong yang disebut knots) dan memasang fungsi polinomial derajat rendah (misalnya kubik) pada masing-masing segmen. Tidak seperti regresi fungsi tangga, model ini memastikan bahwa kurva prediksi tersambung dengan mulus di setiap knot, baik secara nilai fungsi maupun derivatifnya. Salah satu pendekatan yang umum digunakan adalah truncated power basis, yang memungkinkan fleksibilitas bentuk sekaligus menjaga kontinuitas antar segmen.

Sementara itu, smoothing splines mengambil pendekatan yang berbeda. Alih-alih menetapkan secara eksplisit jumlah dan lokasi knot, smoothing spline menganggap bahwa setiap titik data sebagai potential knot dan menyeimbangkan dua tujuan utama: (1) meminimalkan selisih kuadrat antara prediksi dan data, serta (2) menjaga kelicinan (smoothness) dari fungsi prediksi. Penyeimbangan ini dikendalikan oleh sebuah parameter penyetelan (tuning parameter) yang disebut \(\lambda\).

Persiapan Data

Sebagai dasar eksplorasi regresi spline dan smoothing spline, kita akan menggunakan data simulasi. Data ini dibangkitkan sedemikian rupa agar mencerminkan pola hubungan nonlinier kuadratik antara variabel prediktor dan respons. Penambahan komponen noise dengan varians besar dilakukan agar tantangan pemodelan menjadi lebih realistis, serta dapat menunjukkan perbedaan kemampuan masing-masing metode dalam menangkap pola mendasar data.

Secara matematis, data dibangkitkan mengikuti model:

\[ y = 5 + 2x + 3x^2 + \varepsilon,\quad \varepsilon \sim N(0, 5^2) \]

Berikut proses pembangkitan dan visualisasi data menggunakan R:

# Set seed untuk replikasi hasil
set.seed(123)

# Bangkitkan data x dari distribusi Normal(1, 1)
x <- rnorm(1000, mean = 1, sd = 1)

# Bangkitkan noise dari distribusi Normal(0, 5)
epsilon <- rnorm(1000, mean = 0, sd = 5)

# Bentuk data y dengan hubungan kuadratik
y <- 5 + 2 * x + 3 * x^2 + epsilon

Langkah selanjutnya adalah memvisualisasikan sebaran data untuk mendapatkan pemahaman awal mengenai bentuk hubungan antara \(x\) dan \(y\).

# Visualisasi scatter plot dari data simulasi

plot(x, y,
     main = "Sebaran Data Simulasi",
     xlab = "x", ylab = "y",
     col = "orange",
     xlim = c(-2.5, 5), ylim = c(-20, 80))

Dari plot di atas, tampak bahwa data mengikuti pola parabola dengan tingkat sebaran (variansi) yang cukup tinggi. Ini menjadi tantangan bagi model regresi linier sederhana, dan menjadi alasan kuat untuk menggunakan pendekatan regresi nonlinier berbasis spline.

Regression Splines: Piecewise Cubic Polynomial

Regresi spline merupakan pengembangan dari regresi polinomial yang lebih fleksibel dalam menangkap pola nonlinier, karena memungkinkan fungsi polinomial berbeda digunakan di masing-masing segmen domain prediktor. Salah satu bentuk dasar dari regresi spline adalah piecewise cubic polynomial, yaitu pendekatan yang membagi domain \(x\) menjadi beberapa bagian (pieces) dan menerapkan regresi kubik secara terpisah di setiap bagian.

Namun, jika kita langsung memodelkan fungsi polinomial secara terpisah di masing-masing segmen tanpa batasan tambahan, hasilnya akan menjadi tidak kontinu di titik potong antar segmen. Oleh karena itu, dalam praktiknya regresi spline biasanya dibentuk agar kontinu (dan bahkan halus secara derivatif pertama dan kedua) di titik sambung (knots).

Untuk memahami dasar teknik ini, kita akan terlebih dahulu menerapkan pendekatan piecewise cubic polynomial secara manual, yaitu dengan: 1. Membagi data menjadi dua bagian berdasarkan satu titik potong (knot), 2. Memodelkan regresi kubik secara terpisah pada masing-masing subset.

Sebagai ilustrasi awal, kita tetapkan titik potong pada \(x = 1\).

# Tetapkan titik potong (knot)
cutpoint <- 1

# Bagi data menjadi dua subset
data1 <- subset(data.frame(x, y), x <= cutpoint)
data2 <- subset(data.frame(x, y), x > cutpoint)

# Model regresi kubik pada masing-masing subset
mod1 <- lm(y ~ poly(x, 3, raw = TRUE), data = data1)
mod2 <- lm(y ~ poly(x, 3, raw = TRUE), data = data2)

Selanjutnya, kita visualisasikan hasil dua model tersebut dalam satu grafik untuk melihat bentuk kurva yang dihasilkan.

# Plot sebaran data
plot(x, y,
     main = "Piecewise Cubic Polynomial (1 Knot di x = 1)",
     xlab = "x", ylab = "y",
     col = "orange", pch = 16,
     xlim = c(-2.5, 5),
     ylim = c(-20, 80))

# Tambahkan garis batas knot
abline(v = cutpoint, col = "red", lty = 2)

# Prediksi pada subset 1

x_seq1 <- sort(data1$x)
pred1 <- predict(mod1, newdata = data.frame(x = x_seq1))
lines(x_seq1, pred1, col = "blue", lwd = 2)

# Prediksi pada subset 2
x_seq2 <- sort(data2$x)
pred2 <- predict(mod2, newdata = data.frame(x = x_seq2))
lines(x_seq2, pred2, col = "blue", lwd = 2)

# Tambahkan legenda
legend("topleft",
       legend = c("Data", "Model (Piecewise Cubic)", "Titik Potong"),
       col = c("orange", "blue", "red"),
       pch = c(16, NA, NA),
       lty = c(NA, 1, 2),
       lwd = c(NA, 2, 1.5))

Dari visualisasi di atas, tampak bahwa meskipun model pada masing-masing subset menangkap bentuk lengkungan data secara lokal, namun terdapat ketidakterhubungan (diskontinuitas) di titik potong \(x = 1\). Hal ini akan kita perbaiki pada bagian selanjutnya dengan menggunakan pendekatan truncated power basis, yang secara matematis menjamin kontinuitas fungsi di setiap knot.

Regression Splines: Truncated Power Basis

Pendekatan truncated power basis merupakan metode umum dalam membangun model regression splines. Dengan pendekatan ini, kita menyusun model polinomial hingga derajat \(k\) (umumnya \(k = 3\) untuk kubik), dan menambahkan fungsi-fungsi basis tambahan berupa potongan terpotong (truncated) seperti \((x - \xi)^k_+\), di mana \(\xi\) adalah titik potong (knot), dan tanda plus (+) berarti fungsi hanya bernilai jika \(x > \xi\) (selain itu bernilai nol).

Model regresi spline kubik dengan satu titik potong di \(x = 1\) dapat dituliskan sebagai:

\[ y = \beta_0 + \beta_1 x + \beta_2 x^2 + \beta_3 x^3 + \beta_4 (x - 1)^3_+ + \varepsilon \]

Berikut implementasi truncated power basis untuk satu knot di \(x = 1\):

# Bangun truncated basis (x - 1)^3_+
tpb1 <- (x - 1)^3
tpb1[x <= 1] <- 0

# Buat data frame lengkap untuk modeling
df1 <- data.frame(y, x, x2 = x^2, x3 = x^3, tpb1)

# Model regresi spline dengan truncated power basis
mod_spline1 <- lm(y ~ x + x2 + x3 + tpb1, data = df1)
summary(mod_spline1)

Call:
lm(formula = y ~ x + x2 + x3 + tpb1, data = df1)

Residuals:
     Min       1Q   Median       3Q      Max 
-15.4035  -3.4397  -0.0171   3.5701  16.6033 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)   5.1679     0.3012  17.156  < 2e-16 ***
x             2.1702     0.4107   5.284 1.56e-07 ***
x2            2.2650     0.3546   6.387 2.58e-10 ***
x3            0.4614     0.2405   1.918   0.0554 .  
tpb1         -0.6530     0.4210  -1.551   0.1212    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 5.028 on 995 degrees of freedom
Multiple R-squared:  0.7838,    Adjusted R-squared:  0.7829 
F-statistic: 901.7 on 4 and 995 DF,  p-value: < 2.2e-16

Visualisasi hasil model dapat dilakukan dengan membandingkan kurva prediksi terhadap data aktual:

# Urutkan x untuk prediksi halus
x_sorted <- sort(x)
tpb1_sorted <- (x_sorted - 1)^3
tpb1_sorted[x_sorted <= 1] <- 0

# Prediksi dari model spline
df_pred1 <- data.frame(x = x_sorted,
x2 = x_sorted^2,
x3 = x_sorted^3,
tpb1 = tpb1_sorted)

predicted_spline1 <- predict(mod_spline1, newdata = df_pred1)

# Plot hasil prediksi
plot(x, y,
main = "Regression Spline dengan Truncated Power Basis (1 Knot)",
xlab = "x", ylab = "y",
col = "orange", pch = 16,
xlim = c(-2.5, 5),
ylim = c(-20, 80))

lines(x_sorted, predicted_spline1, col = "blue", lwd = 2)

# Tambahkan garis vertikal di titik knot
abline(v = 1, col = "red", lty = 2)
legend("topleft",
       legend = c("Data", "Model Spline", "Knot"),
       col = c("orange", "blue", "red"),
       pch = c(16, NA, NA),
       lty = c(NA, 1, 2),
       lwd = c(NA, 2, 1.5))

Dari grafik tersebut, kita dapat melihat bahwa fungsi prediksi tetap halus di sekitar titik potong \(x = 1\). Ini berbeda dengan piecewise polynomial sebelumnya yang cenderung diskontinu di titik sambung. Fungsi basis \((x - 1)^3_+\) menambahkan fleksibilitas hanya setelah \(x > 1\), sehingga model mampu menyesuaikan bentuk lengkungan dengan lebih lokal tanpa mengganggu bagian kiri.

Langkah selanjutnya adalah menambahkan lebih dari satu titik potong (knot) untuk melihat pengaruh jumlah knot terhadap fleksibilitas model.

Truncated Power Basis dengan 2 Knots

Dengan menambahkan lebih banyak titik potong (knots), model spline menjadi lebih fleksibel dalam menyesuaikan bentuk lengkungan data. Namun, semakin banyak knot juga meningkatkan risiko overfitting. Oleh karena itu, pemilihan jumlah dan posisi knot harus dipertimbangkan dengan hati-hati.

Kita akan menggunakan dua titik potong di \(x = 0\) dan \(x = 2\), serta menyusun fungsi basis truncated power sebagai berikut:

\[ y = \beta_0 + \beta_1 x + \beta_2 x^2 + \beta_3 x^3 + \beta_4 (x - 0)^3_+ + \beta_5 (x - 2)^3_+ + \varepsilon \]

Berikut implementasi dalam R:

# Bangun basis truncated power untuk 2 knots
tpb_0 <- (x - 0)^3
tpb_0[x <= 0] <- 0

tpb_2 <- (x - 2)^3
tpb_2[x <= 2] <- 0

# Buat data frame lengkap
df2 <- data.frame(y, x, x2 = x^2, x3 = x^3, tpb_0, tpb_2)

# Model regresi spline dengan 2 knots
mod_spline2 <- lm(y ~ x + x2 + x3 + tpb_0 + tpb_2, data = df2)
summary(mod_spline2)

Call:
lm(formula = y ~ x + x2 + x3 + tpb_0 + tpb_2, data = df2)

Residuals:
     Min       1Q   Median       3Q      Max 
-15.3669  -3.4032   0.0384   3.5578  16.6694 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)   5.1090     0.2916  17.522  < 2e-16 ***
x             2.1298     0.5831   3.653 0.000273 ***
x2            2.7257     0.7474   3.647 0.000279 ***
x3            0.8064     0.8686   0.928 0.353418    
tpb_0        -0.6505     1.0522  -0.618 0.536567    
tpb_2        -0.7537     0.8282  -0.910 0.363046    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 5.029 on 994 degrees of freedom
Multiple R-squared:  0.7839,    Adjusted R-squared:  0.7828 
F-statistic: 721.2 on 5 and 994 DF,  p-value: < 2.2e-16

Visualisasi hasil model dilakukan seperti sebelumnya:

# Urutkan x untuk prediksi halus
x_sorted <- sort(x)

# Basis untuk x terurut
tpb_0_sorted <- (x_sorted - 0)^3
tpb_0_sorted[x_sorted <= 0] <- 0

tpb_2_sorted <- (x_sorted - 2)^3
tpb_2_sorted[x_sorted <= 2] <- 0

# Data prediksi
df_pred2 <- data.frame(x = x_sorted,
x2 = x_sorted^2,
x3 = x_sorted^3,
tpb_0 = tpb_0_sorted,
tpb_2 = tpb_2_sorted)

predicted_spline2 <- predict(mod_spline2, newdata = df_pred2)

# Plot hasil prediksi
plot(x, y,
     main = "Regression Spline dengan Truncated Power Basis (2 Knots)",
     xlab = "x", ylab = "y",
     col = "orange", pch = 16,
     xlim = c(-2.5, 5),
     ylim = c(-20, 80))

lines(x_sorted, predicted_spline2, col = "blue", lwd = 2)

# Tambahkan garis vertikal di titik-titik knot
abline(v = c(0, 2), col = "red", lty = 2)

legend("topleft",
       legend = c("Data", "Model Spline", "Knots"),
       col = c("orange", "blue", "red"),
       pch = c(16, NA, NA),
       lty = c(NA, 1, 2),
       lwd = c(NA, 2, 1.5))

Model ini memiliki fleksibilitas lebih tinggi dibandingkan model dengan satu knot. Fungsi prediksi memiliki kelengkungan tambahan setelah masing-masing titik potong \(x = 0\) dan \(x = 2\), namun tetap tersambung secara mulus dan halus karena sifat dari basis \((x - \xi)^3_+\).

Pada bagian selanjutnya, kita akan melakukan evaluasi model spline menggunakan pendekatan k-fold cross-validation untuk membandingkan performa model dengan jumlah knot berbeda secara kuantitatif.

Evaluasi Model dengan k-Fold Cross-Validation

Untuk menilai seberapa baik model spline memprediksi data baru, kita lakukan evaluasi menggunakan teknik k-fold cross-validation. Teknik ini membagi data menjadi \(k\) bagian (fold), melatih model pada \(k-1\) bagian, dan mengujinya pada bagian sisanya. Proses diulang sebanyak \(k\) kali dengan bagian test yang berbeda, lalu rata-rata kesalahan prediksi dihitung.

Kita akan membandingkan dua model: - Model A: truncated power basis dengan 1 knot di \(x = 1\), - Model B: truncated power basis dengan 2 knots di \(x = 0\) dan \(x = 2\).

# Fungsi untuk menghitung MSE
mse <- function(actual, predicted) {
  mean((actual - predicted)^2)
}

# Inisialisasi
set.seed(123)
k <- 5
n <- length(x)
folds <- sample(rep(1:k, length.out = n))

# Vektor MSE per fold
mse_mod1 <- numeric(k)
mse_mod2 <- numeric(k)

# Cross-validation loop
for (i in 1:k) {
  # Indeks data latih dan uji
  test_idx <- which(folds == i)
  train_idx <- setdiff(1:n, test_idx)
  
  # Data latih dan uji
  x_train <- x[train_idx]; y_train <- y[train_idx]
  x_test <- x[test_idx]; y_test <- y[test_idx]
  
  # Basis untuk model 1 knot
  df_train1 <- data.frame(
    y = y_train,
    x = x_train,
    x2 = x_train^2,
    x3 = x_train^3,
    tpb1 = pmax(0, (x_train - 1)^3)
  )
  
  df_test1 <- data.frame(
    x = x_test,
    x2 = x_test^2,
    x3 = x_test^3,
    tpb1 = pmax(0, (x_test - 1)^3)
  )
  
  mod1 <- lm(y ~ ., data = df_train1)
  pred1 <- predict(mod1, newdata = df_test1)
  mse_mod1[i] <- mse(y_test, pred1)
  
  # Basis untuk model 2 knots
  df_train2 <- data.frame(
    y = y_train,
    x = x_train,
    x2 = x_train^2,
    x3 = x_train^3,
    tpb_0 = pmax(0, (x_train - 0)^3),
    tpb_2 = pmax(0, (x_train - 2)^3)
  )
  
  df_test2 <- data.frame(
    x = x_test,
    x2 = x_test^2,
    x3 = x_test^3,
    tpb_0 = pmax(0, (x_test - 0)^3),
    tpb_2 = pmax(0, (x_test - 2)^3)
  )
  
  mod2 <- lm(y ~ ., data = df_train2)
  pred2 <- predict(mod2, newdata = df_test2)
  mse_mod2[i] <- mse(y_test, pred2)
}

# Ringkasan hasil
mean_mse_mod1 <- mean(mse_mod1)
mean_mse_mod2 <- mean(mse_mod2)

print(paste("Rata-rata MSE Model 1 Knot :", round(mean_mse_mod1, 3)))
[1] "Rata-rata MSE Model 1 Knot : 25.701"
print(paste("Rata-rata MSE Model 2 Knots:", round(mean_mse_mod2, 3)))
[1] "Rata-rata MSE Model 2 Knots: 25.83"

Hasil evaluasi menunjukkan bahwa:

  • Model A (1 knot di \(x = 1\)) memiliki nilai MSE rata-rata sebesar 25.701.
  • Model B (2 knots di \(x = 0\) dan \(x = 2\)) memiliki nilai MSE rata-rata sebesar 25.83.

Meskipun secara teori model dengan lebih banyak titik potong (knots) seharusnya lebih fleksibel dalam menyesuaikan pola data, dalam kasus ini model yang lebih sederhana (1 knot) justru sedikit lebih baik dalam memprediksi. Selisih nilai MSE sangat kecil, sehingga dari segi performa keduanya dapat dianggap sebanding.

Prinsip parsimoni (Occam’s Razor) dalam pemodelan statistik menyarankan untuk memilih model yang lebih sederhana jika performa serupa, guna menghindari overfitting dan meningkatkan interpretabilitas.

Selanjutnya, kita akan beralih ke pendekatan nonparametrik yang tidak mensyaratkan jumlah dan lokasi knot secara eksplisit, yaitu smoothing spline, yang menyelaraskan kebutuhan fit dan smoothness melalui parameter kontrol regularisasi.

Smoothing Spline

Berbeda dengan regression spline yang membutuhkan penentuan jumlah dan lokasi knot secara eksplisit, smoothing spline secara otomatis memilih fungsi kurva yang mulus berdasarkan kompromi antara dua hal:

  1. Goodness of fit – seberapa dekat kurva mengikuti data,
  2. Smoothness – seberapa halus kurva (tidak terlalu berkelok-kelok).

Kompromi ini dikontrol oleh sebuah parameter regulasi yang disebut smoothing parameter \(\lambda\) (lambda). Nilai \(\lambda\) yang kecil akan menghasilkan kurva yang lebih fleksibel (fit ke data), sedangkan nilai besar akan menghasilkan kurva yang sangat halus (mendekati linier).

Fungsi smooth.spline() secara default akan memilih \(\lambda\) terbaik menggunakan kriteria generalized cross-validation (GCV).

Estimasi Smoothing Spline (default lambda)

# Estimasi smoothing spline secara default (lambda otomatis)
fit_smooth <- smooth.spline(x, y)

# Plot hasil smoothing spline
plot(x, y,
     main = "Smoothing Spline (λ dipilih otomatis via GCV)",
     xlab = "x", ylab = "y",
     col = "orange", pch = 16)

lines(fit_smooth, col = "blue", lwd = 2)

legend("topleft",
       legend = c("Data", "Smoothing Spline"),
       col = c("orange", "blue"),
       pch = c(16, NA),
       lty = c(NA, 1),
       lwd = c(NA, 2))

Dari hasil di atas, dapat diamati bahwa kurva smoothing spline mengikuti pola data dengan halus dan adaptif, tanpa perlu menetapkan titik potong (knots).

Eksplorasi Smoothing Parameter \(\lambda\)

Untuk memahami pengaruh nilai \(\lambda\), kita bisa eksplorasi secara manual dengan parameter spar (smoothing parameter relatif dalam \([0, 1]\)). Nilai kecil berarti kurva fleksibel sedangkan nilai besar berarti kurva lebih halus.

# Visualisasi efek spar (smoothing parameter relatif)

plot(x, y,
     main = "Efek Parameter Smoothing (spar)",
     xlab = "x", ylab = "y",
     col = "gray50", pch = 16)

lines(smooth.spline(x, y, spar = 0.3), col = "blue", lwd = 2)
lines(smooth.spline(x, y, spar = 0.6), col = "green", lwd = 2)
lines(smooth.spline(x, y, spar = 0.9), col = "red", lwd = 2)

legend("topright",
       legend = c("spar = 0.3 (fit tinggi)", "spar = 0.6 (moderat)", "spar = 0.9 (halus)"),
       col = c("blue", "green", "red"),
       lwd = 2)

Kurva dengan spar = 0.3 mengikuti data dengan ketat (bisa overfit), sedangkan spar = 0.9 sangat halus (mendekati linier). Nilai spar = 0.6 bisa menjadi kompromi yang seimbang.

Perbandingan Ringkasan dan Penutup

Selama praktikum ini, kita telah membandingkan dua pendekatan regresi nonlinier berbasis spline: regression splines (dengan basis truncated power) dan smoothing splines. Berikut ringkasan perbandingannya:

Aspek Regression Splines Smoothing Splines
Jenis pendekatan Parametrik (basis fungsi eksplisit) Nonparametrik (penyesuaian adaptif)
Penentuan knot Ditentukan secara eksplisit oleh pengguna Setiap titik data berpotensi menjadi knot
Kompleksitas kontrol Jumlah dan posisi knot Parameter \(\lambda\) / spar
Kemulusan kurva Disesuaikan dengan bentuk basis Dikendalikan langsung oleh penalti smoothness
Risiko overfitting Tinggi jika terlalu banyak knot Dikendalikan oleh \(\lambda\)
Interpretabilitas Lebih mudah dibaca dan dijelaskan Kurva lebih halus namun sulit diinterpretasi

Secara umum:

  • Regression splines lebih cocok saat kita ingin kontrol eksplisit terhadap struktur model dan interpretasi lokal terhadap pengaruh segmen.
  • Smoothing splines lebih unggul dalam hal kemulusan dan kemudahan penggunaan, karena tidak perlu menentukan lokasi knot secara manual.

💡 Dalam praktik analisis data, pemilihan pendekatan spline sangat tergantung pada konteks masalah, tujuan analisis (prediksi vs interpretasi), serta jumlah data.


Refleksi Praktikum

Melalui eksplorasi visual, pemodelan, dan evaluasi performa prediksi, mahasiswa diharapkan memperoleh pemahaman yang lebih dalam mengenai:

  • Konsep basis function regression dalam konteks nonlinier,
  • Perbedaan struktural antara regresi spline parametrik dan nonparametrik,
  • Pentingnya proses cross-validation dalam menilai kualitas model.

Dengan bekal ini, mahasiswa dapat melangkah ke topik regresi yang lebih kompleks seperti generalized additive models (GAM) atau integrasi spline dalam model regresi linear maupun logistik multivariat.