Pemrograman Statistika (Fungsi, OOP dan Optimasi Numerik) - Tugas Responsi 3
Pokok bahasan dalam praktikum STA561 pertemuan 6 dan 7 adalah sebagai berikut:
- Praktikum 6: Pemrograman Fungsi dan OOP di R
- Fungsi
- OOP (Object Oriented Programming) di R
- Class System S3
- Class System S4
- Praktikum 7: Optimasi secara Numerik
- Diferensial
- Integral
- Optimasi secara NUmerik
- Golden Section search
- Newton Rapshon
- Fungsi Optimasi Built-in > Optimasi Satu Variabel (Optimize/Optimise) > Optimasi Lebih dari Satu Variabel (Optim) > Regresi Linier
- MLE: Maximum Likelihood Estimator
- Latihan
Praktikum 6: Pemrograman Fungsi dan OOP
Fungsi
Fungsi digunakan untuk membuat sekumpulan mekanisme dasar yang dijalankan secara simultan.
function(argumen list){
expression
return (value)
}
Contoh 1
angka_acak1 <- function(n,pw){
x <- runif(n)
y <- runif(n)
z <- (x+y)^pw
return(z)
}
angka_acak1(10,2)## [1] 1.6190381 0.3360103 0.6215977 1.4363796 2.4243391 0.2859981 0.7040056
## [8] 0.9756431 2.4239974 0.4982917
Contoh 2
angka_acak2 <- function(n,pw){
x <- runif(n)
y <- runif(n)
z <- (x+y)^pw
return(list(x = x, y = y, z = z))
}
angka_acak2(10,2)## $x
## [1] 0.47164979 0.80560026 0.16714127 0.61014590 0.08337948 0.81595572
## [7] 0.60857190 0.94580033 0.40512597 0.10674867
##
## $y
## [1] 0.4444645 0.8200039 0.9170443 0.2374087 0.1866832 0.1818032 0.9577259
## [8] 0.7121519 0.2608791 0.7532914
##
## $z
## [1] 0.83926541 2.64258895 1.17545844 0.71834885 0.07293387 0.99552287
## [7] 2.45328888 2.74880565 0.44356275 0.73966891
Contoh 3
angka_acak3 <- function(n=10, pw=2){
x <- runif(n)
y <- runif(n)
z <- (x+y)^pw
return(z)
}
angka_acak3()## [1] 1.4345168 0.1563539 1.2025178 1.3182684 0.6968917 0.2911175 1.7571489
## [8] 1.2241553 1.0113047 1.3851274
Contoh 4
angka_acak4 <- function(){
x <- runif(n)
y <- runif(n)
z <- (x+y)^pw
return(z)
}
n <- 5; pw <- 3
angka_acak4()## [1] 1.4284204 0.1105117 3.6780662 1.1528365 2.3088689
Latihan 1
Membuat fungsi Median dari suatu vektor
med <- function(vect){
n <- length(vect)
vects <- sort(vect)
if(n%%2 == 1){
m <- vects[(n+1)/2]}
else {
m <- (vects[n/2] + vects[(n/2) + 1])/2}
return(m)
}
x1 <- c(1,5,3,7,3,4,2,7)
med(x1)## [1] 3.5
Latihan 2
Membuat fungsi Modus dari suatu vektor
modus <- function(vect){
v <- unique(vect)
f <- NULL
for(i in v)
{ banyak <- sum(vect == i)
f <- c(f, banyak)
}
fmax <- max(f)
vf <- cbind(v,f)
mode <- vf[f == fmax,]
return(mode)
}
modus(x1) ## v f
## [1,] 3 2
## [2,] 7 2
Latihan 3
Membuat fungsi penduga parameter pada regresi berganda
# Membuat fungsi
p.est <- function(A) {
if(!is.matrix(A))
stop("input must be on matrix")
x1 <- A[,-1]
y <- A[,1]
one <- rep(1,nrow(A))
x <- cbind(one,x1)
colnames(x) <- paste("x",1:ncol(x),sep="")
b.est <- as.vector(solve(t(x) %*% x) %*% (t(x) %*% y))
names(b.est) <- paste("b",0:(length(b.est)-1),sep="")
fitted.value <- as.vector(x%*%b.est)
error <- as.vector(y-fitted.value)
names(fitted.value) <- names(error) <- 1:nrow(A)
list(beta.est=b.est,fit.val=fitted.value,error=error)
}
# Memasukkan data
Pendapatan <- c(3.5,3.2,3.0,2.9,4.0,2.5,2.3)
Biaya.Iklan <- c(3.1,3.4,3.0,3.2,3.9,2.8,2.2)
Jumlah.Warung <- c(30,25,20,30,40,25,30)
X <- cbind(Pendapatan,Biaya.Iklan,Jumlah.Warung)
p.est(X)## $beta.est
## b0 b1 b2
## -0.21381852 0.89843390 0.01745279
##
## $fit.val
## 1 2 3 4 5 6 7
## 3.094910 3.277176 2.830539 3.184754 3.988185 2.738116 2.286320
##
## $error
## 1 2 3 4 5 6
## 0.40508982 -0.07717642 0.16946108 -0.28475357 0.01181483 -0.23811608
## 7
## 0.01368033
# Melalukan pengecekan dengan fungsi lm
model <- lm(Pendapatan~Biaya.Iklan+Jumlah.Warung)
# Mengeluarkan koefisien dari model regresi
model$coefficients## (Intercept) Biaya.Iklan Jumlah.Warung
## -0.21381852 0.89843390 0.01745279
# Mengeluarkan fitted values
model$fitted.values## 1 2 3 4 5 6 7
## 3.094910 3.277176 2.830539 3.184754 3.988185 2.738116 2.286320
# Mengeluarkan residuals
model$residuals## 1 2 3 4 5 6
## 0.40508982 -0.07717642 0.16946108 -0.28475357 0.01181483 -0.23811608
## 7
## 0.01368033
Latihan 4
Membuat fungsi bernama
three.Myang digunakan untuk menghitung mean, median, dan modus dari suatu vektor modus (tanpa mengunakan fungsi mean, quantile maupun fungsi instan yang telah tersedia di R).Hitung mead, median, modus dari X di bawah ini dengan menggunakan fungsi
three.Mtersebut
# Membuat fungsi
three.M <- function(vect){
# menghitung banyak data
n <- length(vect)
# menghitung rerata
jumlah <- sum(vect)
rerata <- jumlah/n
# menghitung median
vects <- sort(vect) # mengurutkan data
if(n%%2 == 1){me <- vects[(n+1)/2]}
else {me <- (vects[n/2] + vects[(n/2) + 1])/2}
# menghitung modus
v <- unique(vect)
f <- NULL
for(i in v){
banyak <- sum(vect == i)
f <- c(f, banyak)
}
fmax <- max(f)
vf <- cbind(v,f)
mode <- vf[f == fmax,]
# output
list3 <- list("Mean:" = rerata,
"Median:" = me,
"Modus:" = mode)
return(list3)
}
# Menghitung Mean, Median, Modus suatu data berdistribusi Binomial
set.seed(123)
x2 <- rbinom(100, 10, 0.5)
three.M(x2)## $`Mean:`
## [1] 4.99
##
## $`Median:`
## [1] 5
##
## $`Modus:`
## v f
## [1,] 6 24
## [2,] 5 24
Object Oriented Programming / Pemrograman Berbasis Objek
- PBO menitikberatkan pada identifikasi objek-objek yang terlibat dalam sebuah program dan bagaimana objek tersebut saling berinteraksi.
- Pada PBO, program terdiri dari beberapa objek.
- Prinsip PBO yaitu: a) Abtraksi, b) Enkapsulasi, c) Inheritance, dan d) Polymorphism.
- Pengembangan PBO di R menggunakan Class System S3 dan Class System S4.
Object - S3
Suatu _class_ dalam system S3 tidak didefinisikan dengan ketat. Fungsi class digunakan untuk menjadikan sebuah objek menjadi class yang diinginkan.
Contoh 1
A1 <- c(1:10)
A2 <- matrix(A1,2,5)
class(A1); class(A2)## [1] "integer"
## [1] "matrix" "array"
A3 <- 1:12
A4 <- letters[1:12]
B1 <- data.frame(A3,A4)
B1## A3 A4
## 1 1 a
## 2 2 b
## 3 3 c
## 4 4 d
## 5 5 e
## 6 6 f
## 7 7 g
## 8 8 h
## 9 9 i
## 10 10 j
## 11 11 k
## 12 12 l
# menampilkan class data fram B1
class(B1)## [1] "data.frame"
# mengambil kolom A4 dari data frame B1
B1$A4## [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l"
A5 <- 10 + A3 + rnorm(12)
# membuat model linear
B2 <- lm(A5~A3)
B2##
## Call:
## lm(formula = A5 ~ A3)
##
## Coefficients:
## (Intercept) A3
## 10.3946 0.9661
# melihat class B2
class(B2)## [1] "lm"
# melihat daftar methos yang terdapat pada class B2 (lm: linear modelling)
methods(class = class(B2))## [1] add1 alias anova case.names coerce
## [6] confint cooks.distance deviance dfbeta dfbetas
## [11] drop1 dummy.coef effects extractAIC family
## [16] formula hatvalues influence initialize kappa
## [21] labels logLik model.frame model.matrix nobs
## [26] plot predict print proj qr
## [31] residuals rstandard rstudent show simulate
## [36] slotsFromS3 summary variable.names vcov
## see '?methods' for accessing help and source code
# ringkasa model linier B2
summary(B2)##
## Call:
## lm(formula = A5 ~ A3)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.70634 -0.37935 -0.03672 0.38335 1.32502
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 10.39462 0.51345 20.25 1.91e-09 ***
## A3 0.96614 0.06976 13.85 7.51e-08 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.8343 on 10 degrees of freedom
## Multiple R-squared: 0.9504, Adjusted R-squared: 0.9455
## F-statistic: 191.8 on 1 and 10 DF, p-value: 7.514e-08
# melihat daftar kolom/output dari linier model
names(B2)## [1] "coefficients" "residuals" "effects" "rank"
## [5] "fitted.values" "assign" "qr" "df.residual"
## [9] "xlevels" "call" "terms" "model"
# mengambil "koefesien" lm B2
B2[1]## $coefficients
## (Intercept) A3
## 10.3946172 0.9661381
Mengubah menjadi Class Baru
1) Pengubahan class secara Langsung
Ilustrasi 1:
Membuat object dengan nama Mobil1
# Membuat object Mobil1 dari class list
Mobil1 <- list(Nama = "Toyot",
Panjang = 3.5,
Lebar = 2,
Kecepatan = 180)
# melihat class object Mobil1
class(Mobil1)## [1] "list"
# mengubah class object Mobil1 -> class "mobil"
class(Mobil1) <- "mobil"
class(Mobil1)## [1] "mobil"
Membuat object dengan nama Mobil2
# Membuat object Mobil2 dari class list
Mobil2 <- list(Nama = "Suzuki",
Panjang = 1,
Lebar = 1.8,
Kecepatan = 150)
# mengubah class Mobil2 dari list -> mobil
class(Mobil2) <- "mobil"
class(Mobil2)## [1] "mobil"
2) Pengubahan class menggunakan Fungsi Konstruktor
Fungsi konstruktor berfungsi untuk melakukan screening sebelum menambahkan class
Mobil <- function(Nama,Panjang,Lebar,Kecepatan){
# screening ukuran
if(Panjang<2 || Lebar<1.5 || Kecepatan<80)
# program behenti jika tidak memenuhi kondisi di atas
stop("atribut tidak sesuai")
# assign ke dalam object "Mobil"
Mobil <- list(Nama=Nama, Panjang=Panjang,
Lebar=Lebar, Kecepatan=Kecepatan)
# pengubahan class list -> "mobil"
class(Mobil) <- "mobil"
Mobil
}Menambahkan data object menggunakan class “Mobil”
# Contoh data yang sesuai dengan kondisi screening
Mobil3 <- Mobil(Nama="Daihatsu",
Panjang=3,
Lebar=1.9,
Kecepatan=120)
Mobil3## $Nama
## [1] "Daihatsu"
##
## $Panjang
## [1] 3
##
## $Lebar
## [1] 1.9
##
## $Kecepatan
## [1] 120
##
## attr(,"class")
## [1] "mobil"
# Contoh data yang sesuai dengan kondisi screening
Mobil4 <- Mobil(Nama="Toyota",
Panjang=1.8,
Lebar=1.9,
Kecepatan=120)
Fungsi Aksesor
Fungsi aksesor digunakan untuk mengakses data dalam class. Pengaksesan data dalam class secara langsung dengan menggunakan nama_object$data_yg_diakses tidak direkomendasikan.
1) Mengakses secara Langsung
Mobil2$Nama; Mobil3$Panjang## [1] "Suzuki"
## [1] 3
2) Mengakses menggunakan Fungsi Aksesor
# Membuat fungsi aksesor Nama & Kecepatan
nama <- function(objek)objek$Nama
panjang <- function(objek)objek$Panjang
# Mengakses data nama & kecepatan
nama(Mobil2); panjang(Mobil3)## [1] "Suzuki"
## [1] 3
Fungsi Generik
Contoh pada method print
Dalam ilustrasi class mobil di atas, method print bawaan R menghasilkan output 4 data seperti di bawah ini.
print(Mobil1)## $Nama
## [1] "Toyot"
##
## $Panjang
## [1] 3.5
##
## $Lebar
## [1] 2
##
## $Kecepatan
## [1] 180
##
## attr(,"class")
## [1] "mobil"
Method print akan disesuaikan kebutuhan yakni mengeluarkan output hanya berupa data nama dan kecepatan, sehingga perlu membuat fungsi print untuk class mobil
print.mobil <- function(objek){
print(cat("Nama : ", nama(objek), "\n",
"Panjang : ", panjang(objek),
sep=" "))
}
Mobil1## Nama : Toyot
## Panjang : 3.5NULL
Object - S4
- Sistem objek S4 mengatasi kekurangan dalam sistem objek S3
- Mendefenisikan class baru
setClass("class.name",
representation(x="type"),
prototype(x="..."))
- Mendefinisikan objek baru dari class tertentu
new(class.name,…)
Membuat Object S4
1) Tanpa Fungsi Konstruktor
# membuat class dengan nama "car"
setClass("car", representation(Nama="character",
Panjang="numeric",
Lebar="numeric",
Kecepatan="numeric"))
# membuat objek bernama "Car1" dari class "car"
Car1 <- new("car", Nama="Toyota",
Panjang=3.5,
Lebar=2,
Kecepatan=180)
Car1## An object of class "car"
## Slot "Nama":
## [1] "Toyota"
##
## Slot "Panjang":
## [1] 3.5
##
## Slot "Lebar":
## [1] 2
##
## Slot "Kecepatan":
## [1] 180
2) Dengan Menggunakan Fungsi Konstruktor
Car <- function(Nama,Panjang,Lebar,Kecepatan){
if(Panjang<2 || Lebar<1.5 || Kecepatan<80)
stop("atribut tidak sesuai")
new("car", Nama=Nama,
Panjang=Panjang,
Lebar=Lebar,
Kecepatan=Kecepatan)
}
Car2 <- Car("Suzuki", 2.4, 1.8, 150)
Car2## An object of class "car"
## Slot "Nama":
## [1] "Suzuki"
##
## Slot "Panjang":
## [1] 2.4
##
## Slot "Lebar":
## [1] 1.8
##
## Slot "Kecepatan":
## [1] 150
class(Car2); class(Mobil1)## [1] "car"
## attr(,"package")
## [1] ".GlobalEnv"
## [1] "mobil"
Akses terhadap Slot
1) Akses secara Langsung
Akses terhadap slot class secara langsung secara umum dengan syntax object_s4@data_yg_diakses
# mengakses data Nama dari object Car1
Car1@Nama## [1] "Toyota"
# mengakses data Kecepatan dari object Car2
Car2@Kecepatan## [1] 150
2) Akses menggunakan Fungsi Aksesor
# Fungsi aksesor
nama1 <- function(objek)objek@Nama
kecepatan1 <- function(objek)objek@Kecepatan# mengakses data nama dari object Car1
nama1(Car1)## [1] "Toyota"
# mengakses data kecepatan dari object Car2
kecepatan1(Car2)## [1] 150
Class Method
Secara umum syntax dalam membuat class method adalah sebagai berikut:
setMethod("method", "class.name", function(...){...})
Contoh
setMethod(show, "car", function(object) {
print(cat("Nama : ", nama1(object), "\n",
"Kecepatan : ", kecepatan1(object),
sep=" ")
)}
)
Car1## Nama : Toyota
## Kecepatan : 180NULL
Mencipatkan Fungsi Generik S4
Secara umum syntax untuk membuat fungsi generik baru adalah sebagai berikut.
setGeneric("fungsibaru",
function(objek)
standarGeneric("fungsibaru"))
Praktikum 7: Optimasi secara Numerik
Latihan 1: Fungsi Integral
Soal 1
- Carilah hasil integral tak tentu berikut menggunakan fungsi
yac_strdari packagesRyacas\(\int x^2 + 4 dx\)
# install.packages("Ryacas")
library(Ryacas)##
## Attaching package: 'Ryacas'
## The following object is masked from 'package:stats':
##
## integrate
## The following objects are masked from 'package:base':
##
## %*%, diag, diag<-, lower.tri, upper.tri
yac_str("Integrate(x) x^2 + 4")## [1] "x^3/3+4*x"
- Carilah hasil integral tentu berikut menggunakan fungsi
integrate\(\int_{-10}^{10} x^2 + 4 dx\)
f1 <- function(x) x^2 + 4
integrate(f1, lower=-10, upper=10)## 746.6667 with absolute error < 8.3e-12
Soal 2
- Carilah hasil integral berikut \(\int t^4 e^{-t} dt\)
yac_str("Integrate(t) t^4 * Exp(-t)")## [1] "4*(3*((-2)*(t+1)*Exp(-t)-t^2*Exp(-t))-t^3*Exp(-t))-t^4*Exp(-t)"
- Carilah hasil integral berikut \(\int_{0}^{\infty} t^4 e^{-t} dt\)
f2 <- function(t) t^(4) * exp(-t)
integrate(f2, lower = 0, upper = Inf)## 24 with absolute error < 2.2e-05
gamma(5)## [1] 24
Latihan 2: Fungsi Diferensial
Cari diferensial dari fungsi \(e(x^2)\) menggunakan fungsi D atau deriv
xfs <- expression(exp(x^2))
D(xfs, "x")## exp(x^2) * (2 * x)
xturunan <- deriv(~x^2, "x")
x <- 2
eval(xturunan)## [1] 4
## attr(,"gradient")
## x
## [1,] 4
Optimasi Numerik
Optimasi merupakan proses untuk mencari kondisi yang optimum atau dalam arti paling menguntungkan, sehingga dapat berupa maksimasi atau minimasi.
Beberapa metode statistik menggunakan metode pendugaan nilai optimum dari suatu fungsi tujuan, seperti Metode Kemungkinan Maksimum (likelihood) dan Metode Kuadrat Terkecil.
Metode untuk optimasi numerik,diantaranya:
* Golden Section Search
* Newton-Raphson
* Nelder-Mead
A. Golden Section Search (GSS)
Algoritma Golden Section digunakan untuk menyelesaikan NLP (Non-Linier Programming). GSS menggunakan prinsip “mengurangi daerah batas x yang mungkin menghasilkan nilai fungsi obyektif optimum (maksimum atau minimum) secara iteratif (berulang)”.
* Untuk mendapatkan sebuah titik baru yang simetris, dibutuhkan nilai r (Golden Ratio).
* Batas awal GSS sudah ditentukan.
* GSS merupakan teknik optimasi satu variabel.
Tahapan Optimasi
1. Menentukan range/interval \([a,b]\), \(a\): batas bawah, \(b\): batas atas.
2. Menentukan nilai fungsi di titik \(a\) atau \(f(a)\), dan nilai fungsi di tiitk \(b\) atau \(f(b)\).
3. Menentukan batas baru \(x_{1}\) yang berada dalam \([a,b]\), dimana \(x_{1} = \frac{b-(b-a)*2)}{\sqrt{5}+1}\).
4. Menentukan batas baru \(x_{2}\) yang berada dalam \([a,b]\), dimana \(x_{2} = \frac{a+(b-a)*2)}{\sqrt{5}+1}\).
5. Menentukan nilai fungsi dari \(f(x_{1})\) dan \(f(x_{2})\).
6. Pilihan:
Maksimasi
* Jika \(f(x_{1})>f(x_{2})\), titik optimal berada pada \([a,x_{2}]\), sehingga diperoleh batas baru \(a=a, b=x_{2}\).
* Jika \(f(x_{1})<f(x_{2})\), titik optimal berada pada \([x_{1},b]\), sehingga diperoleh batas baru \(a=x_{1}, b=b\).
Minimasi
* Jika \(f(x_{1})<f(x_{2})\), titik optimal berada pada \([a,x_{2}]\), sehingga diperoleh batas baru \(a=a, b=x_{2}\).
* Jika \(f(x_{1})>f(x_{2})\), titik optimal berada pada \([x_{1},b]\), sehingga diperoleh batas baru \(a=x_{1}, b=b\).
7. Melakukan iterasi sampai diperoleh \(\left | a-b \right | < toleransi\)
Contoh 1 Menghitung nilai maksimum fungsi \(f(x)=-x^2+6x+10\)
x.max <- function(f,a,b,tol=0.0000000001){
ratio <- 2/(sqrt(5)+1)
x1 <- b - ratio * (b-a)
x2 <- a + ratio * (b-a)
f1 <- f(x1)
f2 <- f(x2)
while(abs(b-a) > tol) {
if (f1 > f2){
b <- x2
x2 <- x1
f2 <- f1
x1 <- b - ratio * (b-a)
f1 <- f(x1)
} else{
a <- x1
x1 <- x2
f1 <- f2
x2 <- a + ratio * (b-a)
f2 <- f(x2)
}
}
return((a+b)/2)
}
f <- function(x){
-1*x^2+6*x+10
}# nilai maks jika a=1, b=2
x.max(f,1,2)## [1] 2
# nilai maks jika a=3, b=5
x.max(f,3,5)## [1] 3
x <- seq(-10, 10, by = 0.001)
f_x <- -1*x^2+6*x+10
plot(x,f_x, type = "l",
main = "Grafik Fungsi 2x^2+6x+10",
xlab = "nilai x",
ylab = "nilai y",
xlim = c(-10,10),
ylim = c(0,25))
abline(v=2, lty=3, lwd=1, col="red")
abline(v=3, lty=3, lwd=1, col="red")
abline(v=7, lty=3, lwd=1, col="red") # nilai maks jika a=6, b=10B. Newton Rapshon
Iterasi pada metode ini terus berjalan sampai \(f'(x_{n-1})\approx 0\) atau lebih kecil dari nilai toleransi
Proses Iterasi
newtonr <- function(fx, x0=1){
fx1 <- deriv(fx, "x") #turunan pertama
fx2 <- deriv(D(fx,"x"), "x") #turunan kedua
e <- 1000
while (e > 1e-6) {
x <- x0
f1 <- attr(eval(fx1), "gradient")[1]
f2 <- attr(eval(fx2), "gradient")[1]
e <- abs(f1) #bisa juga e <- abs(x1-x0)
x1 <- x0-f1/f2
x0 <- x1
}
return(x1)
}Contoh 1 Menghitung nilai minimum dari fungsi \(f(x) = 6x^{2}-x-12\)
fx1 <- expression(6*x^2-x-12)
newtonr(fx1)## [1] 0.08333333
# plot fungsi 6*x^2-x-12
plot(x = seq(-10,10, by=0.001), y = 6*x^2-x-12,
type = "l",
xlab = "nilai x",
ylab = "nilai f(x)",
xlim = c(-10,10),
ylim = c(-15,50))
abline(v = 0.083333, lty =3, lwd = 1, col = "blue")
Contoh 2 Menghitung nilai minimum dari fungsi \(f(x) = e^{-x} + x^4\)
fx2 <- expression(exp(-x) + x^4)
newtonr(fx2)## [1] 0.5282519
curve(exp(-x) + x^4, ylab = "nilai f(x)")
abline(v=0.5282519, lty=3, lwd=1, col="brown")
Contoh 3 Menghitung nilai minimum dari \(f(x) = 2x^{2} - x\)
# hitung f(x)
fx3 <- expression(x^2 - x)
# nilai minimum
newtonr(fx3)## [1] 0.5
# plot fungsi
curve(x^2 - x, ylab = "fx3")
abline(v = newtonr(fx3), lty = 3, lwd = 1, col = "brown")C. Fungsi Optimasi Built-in
Pada R algoritma Nelder-Mead (salah satu metode optimasi untuk fungsi lebih dari satu variabel) diterapkan pada fungsi:
* optimize() atau optimize() untuk fungsi satu variabel
* optim() untuk fungsi lebih dari satu variabel
Optimasi 1 Variabel: optimize()
Contoh 1
Menghitung nilai minimun dari \(f(x) = \left (x-\frac{1}{3} \right )^{2}\)
f <- function(x,a){
(x-a)^2
}
# titik minimum (x,y) dg fungsi optimize(nama_fungsi, vektor_interval)
titikMin <- optimize(f, c(0,1), tol=0.0001, a=1/3)
titikMin## $minimum
## [1] 0.3333333
##
## $objective
## [1] 0
Contoh 2 Menghitung titik maksimum dari fungsi \(f(x) = -x^2+4x+5\)
Maksimum pada interval [-1,5]
f <- function(x){-x^2+4*x+5}
# titik maksimum (x,y) dg fungsi optimize(nama_fungsi, vektor_interval)
titikMaks <- optimise(f, c(-1,1), maximum = TRUE)
titikMaks## $maximum
## [1] 0.999959
##
## $objective
## [1] 7.999918
curve(f, from=-1, to=5)
abline(v=2, h=9, lty=3, lwd=1, col="brown")
Maksimum pada interval [0,3]
titikMaks <- optimise(f, c(0,3), maximum = TRUE)
titikMaks## $maximum
## [1] 2
##
## $objective
## [1] 9
curve(f, from=0, to=3)
abline(v=2, h=9, lty=3, lwd=1, col="brown")
Contoh 3 Menghitung titik maksimum dan minimum dari fungsi \(f(x) = sin(x) + sin(2x) + cos(3x)\)
f3 <- function(x) sin(x) + sin(2*x) + cos(3*x)
# plot fungsi f3
curve(f3, from=0, to=2*pi) Minimum Lokal
optimize(f3, interval = c(0, 2*pi))## $minimum
## [1] 3.033129
##
## $objective
## [1] -1.054505
Minimum Global
optimize(f3, interval = c(4, 2*pi))## $minimum
## [1] 5.273383
##
## $objective
## [1] -2.741405
Maksimum Lokal
optimize(f3, interval = c(0,2*pi), maximum = TRUE)## $maximum
## [1] 4.0598
##
## $objective
## [1] 1.096473
Maksimum Global
optimize(f3, interval = c(0,1.5), maximum = TRUE)## $maximum
## [1] 0.3323289
##
## $objective
## [1] 1.485871
Contoh 4 ……..
Optimasi Lebih Dari 1 Variabel: optim()
Contoh 1
Carilah nilai \(x_{1}\) dan \(x_{2}\) agar fungsi berikut \(f(xf(x_{1}, x_{2}) = 100 \left ( x_{2} - x_{1}^{2} \right )^{2} + \left ( 1-x_{1} \right )^{2}_{1}, x_{2}) = 100 \left ( x_{2} - x_{1}^{2} \right )^{2} + \left ( 1-x_{1} \right )^{2}\) minimum!
f4 <- function(x){
x1 <- x[1]
x2 <- x[2]
100 * (x2 - (x1)^2)^2 + (1-x1)^2
}
# mencari x1 dan x2 fungsi
optim(c(-1.2,1),f4)## $par
## [1] 1.000260 1.000506
##
## $value
## [1] 8.825241e-08
##
## $counts
## function gradient
## 195 NA
##
## $convergence
## [1] 0
##
## $message
## NULL
Regresi Linier
Contoh Kasus
Lakukan pendugaan parameter regresi dengan memiminimumkan Jumlah Kuadrat Galat (residual sum of square) dari data berikut. Kemudian bandingkan hasilnya dengan output dari fungsi lm!
# data frame
data5 <- data.frame(x = c(1,2,3,4,5,6),
y = c(1,3,5,6,8,12))
data5## x y
## 1 1 1
## 2 2 3
## 3 3 5
## 4 4 6
## 5 5 8
## 6 6 12
JKG <- function(data,b){
with(data, sum((b[1] + b[2]*x - y)^2))
}
hasil1 <- optim(par = c(1,1), fn = JKG, data = data5)
hasil1## $par
## [1] -1.266302 2.028449
##
## $value
## [1] 2.819048
##
## $counts
## function gradient
## 67 NA
##
## $convergence
## [1] 0
##
## $message
## NULL
hasil2 <- lm(y = x, data = data5)## Warning in if (ret.y) z$y <- y: the condition has length > 1 and only the first
## element will be used
hasil2##
## Call:
## lm(data = data5, y = x)
##
## Coefficients:
## (Intercept) y
## 0.7327 0.4744
# Plot regresi
plot(data5)
abline(hasil1$par, col=4)hasil1$par## [1] -1.266302 2.028449
hasil2$coefficients## (Intercept) y
## 0.7327394 0.4743875
hasil1$value## [1] 2.819048
# Jumlah Kuadrat Galat
sum(hasil2$residuals^2)## [1] 0.6592428
D. MLE: Maximum Likelihood Estimator
Maximum Likelihood Estimator merupakan metode yang paling sering digunakan untuk menduga parameter sebaran.
# install.packages("bbmle")
library(bbmle)## Loading required package: stats4
Contoh 1: Sebaran Normal
Jika \(x_{1}, x_{2}, ..., x_{n}\) berasal dari peubah acak \(X\sim N(\mu,\sigma)\) berikut penduga \(\mu\) dan \(\sigma\) menggunakan MLE.
- menggunakan fungsi
optim()
lnorm <- function (para ,xd){
nilai <- -1*sum(dnorm(xd, mean = para[1], sd = para[2], log = TRUE))
return (nilai)
}
set.seed(2)
x <- rnorm(10,2,5)
hasil <- optim(c(1,1), lnorm, xd = x)
hasil## $par
## [1] 3.056350 4.671425
##
## $value
## [1] 29.6057
##
## $counts
## function gradient
## 63 NA
##
## $convergence
## [1] 0
##
## $message
## NULL
- menggunakan fungsi
mle()
lnorm <- function (mean, sd){
nilai <- -1*sum(dnorm(x, mean = mean, sd = sd, log = TRUE))
return (nilai)
}
suppressWarnings(
estnorm <- mle2(minuslogl = lnorm, start=list(mean = 1, sd = 2))
)
summary(estnorm)## Maximum likelihood estimation
##
## Call:
## mle2(minuslogl = lnorm, start = list(mean = 1, sd = 2))
##
## Coefficients:
## Estimate Std. Error z value Pr(z)
## mean 3.0557 1.4775 2.0682 0.03862 *
## sd 4.6722 1.0447 4.4721 7.744e-06 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## -2 log L: 59.2114
Latihan
Pendugaan Regresi Linier Menggunakan MLE
Model regresi linier sederhana:
\(Y_{i} = B_{0} + B_{1}X_{i} + \varepsilon_{i}\) dimana \(i = 1,2,...n\)
1. Membangkitkan Bilangan Acak
# Membangkitkan bilangan acak X ~ N(mean=12, sd=4)
data.x <- rnorm(n = 50, mean = 12, sd = 4)# Membangkitkan nilai Y dengan menentukan nilai B0 adalah 8 dan B1 adalah 3
B0 <- 8
B1 <- 3
# Menentukan error dari data dengan sd=1
error.sd <- 1
error <- rnorm(n = 50, mean = 0, sd = 1)
data.y <- B0 + B1 * data.x + error
# Plot
plot(data.x, data.y) Dari plot di ata terlihat bahwa data X dan Y yang dibangkitkan memiliki hubungan linier.
2. Pendugaan Regresi Linier dengan MLE Diasumsikan mengikuti sebaran Normal \(\mu = B_{0} + B_{1}X_{1}; \sigma=sd\).
Akan dicari nilai penduga \(B_{0}\) dan \(B_{1}\)
# MLE
lm.loss <- function(parameter){
B0.parameter <- parameter[1] # parameter B0/intercept
B1.parameter <- parameter[2] # parameter B1
error.sigma <- parameter[3] # standar deviasi
# prosedur optimasi: dibuat nilai toleranis jika standar deviasi tidak valid
# misal negatif, maka dikembalikan kepada deviance yang sangat tinggi
if(error.sigma < 0){ deviance <- 10000000}
if(error.sigma > 0){
likelihoods <- dnorm(data.y,
mean = B0.parameter + B1.parameter*data.x,
sd = error.sigma)
log.likelihoods <- log(likelihoods)
deviance <- -2 * sum(log.likelihoods)
}
return(deviance)
}
parameter.fits <- optim(par = c(1,1,10),
fn = lm.loss,
hessian = T)
parameter.fits## $par
## [1] 8.187312 2.976223 1.135375
##
## $value
## [1] 154.6134
##
## $counts
## function gradient
## 144 NA
##
## $convergence
## [1] 0
##
## $message
## NULL
##
## $hessian
## [,1] [,2] [,3]
## [1,] 77.57495533 953.843970 0.01977574
## [2,] 953.84397028 13472.658955 0.23635901
## [3,] 0.01977574 0.236359 155.25934269
Nilai $parameter pada output di atas menyatakan
\(B_{0} = 7.847328\) \(B_{1} = 3.020590\) \(sd = 1.075546\)
3. Membandingkan dengan FUngsi lm() Membandingkan hasil optimasi MLE poin 2 dengan fungsi regresi linier menggunakan fungsi lm().
regresi <- lm(data.y ~ data.x)
regresi##
## Call:
## lm(formula = data.y ~ data.x)
##
## Coefficients:
## (Intercept) data.x
## 8.187 2.976
Diperoleh bahwa nilai penduga \(B_{0}\) dan \(B_{1}\) yang dihasilkan dengan optimasi MLE tidak jauh berbeda (hampir sama) dengan yang dihasilkan fungsi lm().
Referensi
Dito, G.A. Praktikum Komputasi Statistika. Diakses dari https://bookdown.org/gerryalfadito/praktikum-komputasi-statistika/
Raharjo, Mulianto. (2021). STA 561 Pemrograman Statistika: Pemrograman Fungsi & OOP dan Optimasi . Diakses dari https://newlms.ipb.ac.id/
Soleh. A.M. (2021). STA 561 Pemrograman Statistika: Pemrograman Fungsi R dan Optimasi secar Numerik. Diakses dari https://newlms.ipb.ac.id/